/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package org.openatom.ubml.model.common.definition.commonmodel.json.object;

import com.fasterxml.jackson.core.JsonGenerator;
import org.openatom.ubml.model.common.definition.cef.IGspCommonDataType;
import org.openatom.ubml.model.common.definition.cef.collection.BaseList;
import org.openatom.ubml.model.common.definition.cef.element.GspAssociationKey;
import org.openatom.ubml.model.common.definition.cef.json.CefNames;
import org.openatom.ubml.model.common.definition.cef.json.SerializerUtils;
import org.openatom.ubml.model.common.definition.cef.json.element.CefFieldSerializer;
import org.openatom.ubml.model.common.definition.cef.json.object.GspCommonDataTypeSerializer;
import org.openatom.ubml.model.common.definition.commonmodel.IGspCommonElement;
import org.openatom.ubml.model.common.definition.commonmodel.IGspCommonObject;
import org.openatom.ubml.model.common.definition.commonmodel.entity.GspCommonObject;
import org.openatom.ubml.model.common.definition.commonmodel.entity.object.GspUniqueConstraint;
import org.openatom.ubml.model.common.definition.commonmodel.json.CommonModelNames;
import org.openatom.ubml.model.common.definition.commonmodel.json.element.CmElementSerializer;

/**
 * The Json Serializer Of Common Model Object
 *
 * @ClassName: CmObjectSerializer
 * @Author: Benjamin Gong
 * @Date: 2021/1/11 17:13
 * @Version: V1.0
 */
public abstract class CmObjectSerializer extends GspCommonDataTypeSerializer {

    private final String parentObjectID = "ParentObjectID";

    //BaseProp
    @Override
    protected void writeExtendCdtBaseProperty(IGspCommonDataType dataType, JsonGenerator writer) {
        GspCommonObject bizObject = (GspCommonObject)dataType;
        writeContainChildObjects(writer, bizObject);
        SerializerUtils.writePropertyName(writer, CommonModelNames.REPOSITORY_COMPS);
        SerializerUtils.writePropertyValue_Object(writer, bizObject.getRepositoryComps());
        SerializerUtils.writePropertyValue(writer, CommonModelNames.REF_OBJECT_NAME, bizObject.getRefObjectName());
        SerializerUtils.writePropertyValue(writer, CommonModelNames.OBJECT_TYPE, bizObject.getObjectType().getValue());
        //扩展对象属性
        writeExtendObjectBaseProperty(writer, bizObject);
    }

    private void writeContainChildObjects(JsonGenerator writer, GspCommonObject bizObject) {
        SerializerUtils.writePropertyName(writer, CommonModelNames.CONTAIN_CHILD_OBJECTS);
        //[
        SerializerUtils.WriteStartArray(writer);
        if (bizObject.getContainChildObjects().size() > 0) {

            for (IGspCommonObject childObject : bizObject.getContainChildObjects()) {
                serialize(childObject, writer, null);
            }
        }
        //]
        SerializerUtils.WriteEndArray(writer);
    }



    //SelfProp
    @Override
    protected final void writeExtendCdtSelfProperty(IGspCommonDataType dataType, JsonGenerator writer) {
        GspCommonObject bizObject = (GspCommonObject)dataType;

//        SerializerUtils.writePropertyValue(writer, CommonModelNames.LogicDelete, bizObject.LogicDelete);
        SerializerUtils.writePropertyValue(writer, CommonModelNames.GENERATE_ID, bizObject.getColumnGenerateID());
        writeContainConstraints(writer, bizObject);
        SerializerUtils.writePropertyValue(writer, CommonModelNames.ORDERBY_CONDITION, bizObject.getOrderbyCondition());
        SerializerUtils.writePropertyValue(writer, CommonModelNames.FILTER_CONDITION, bizObject.getFilterCondition());
//        SerializerUtils.writePropertyValue(writer, CommonModelNames.ModifiedDateElementID, bizObject.ModifiedDateElementID);
//        SerializerUtils.writePropertyValue(writer, CommonModelNames.CreatorElementID, bizObject.CreatorElementID);
//        SerializerUtils.writePropertyValue(writer, CommonModelNames.CreatedDateElementID, bizObject.CreatedDateElementID);
//        SerializerUtils.writePropertyValue(writer, CommonModelNames.ModifierElementID, bizObject.ModifierElementID);
//
//        SerializerUtils.writePropertyValue(writer, CommonModelNames.RecordDelData, bizObject.RecordDelData);
        SerializerUtils.writePropertyValue(writer, CommonModelNames.IS_READ_ONLY, bizObject.getIsReadOnly());
        SerializerUtils.writePropertyValue(writer, CommonModelNames.IS_VIRTUAL, bizObject.getIsVirtual());
        SerializerUtils.writePropertyValue(writer, CommonModelNames.BELONG_MODEL_ID, bizObject.getBelongModelID());
        //writeGspHirarcheInfo(writer, bizObject);
        writeGspAssociationKeyCollection(writer, bizObject);

        SerializerUtils.writePropertyValue(writer, CommonModelNames.STATE_ELEMENT_ID, bizObject.getStateElementID());
        //前端使用ParentObjectId
        if (bizObject.getParentObject() != null) {
            SerializerUtils.writePropertyValue(writer, parentObjectID, bizObject.getParentObject().getID());
        }

        //扩展对象属性
        writeExtendObjectSelfProperty(writer, bizObject);
    }

    private void writeContainConstraints(JsonGenerator writer, GspCommonObject bizObject) {
        //ContainConstraints：
        SerializerUtils.writePropertyName(writer, CommonModelNames.CONTAIN_CONSTRAINTS);
        //[
        SerializerUtils.WriteStartArray(writer);
        if (bizObject.getContainConstraints() != null && bizObject.getContainConstraints().size() > 0) {
            for (GspUniqueConstraint item : bizObject.getContainConstraints()) {
                SerializerUtils.writeStartObject(writer);
                SerializerUtils.writePropertyValue(writer, CommonModelNames.ID, item.getId());
                SerializerUtils.writePropertyValue(writer, CommonModelNames.CODE, item.getCode());
                SerializerUtils.writePropertyValue(writer, CommonModelNames.NAME, item.getName());
                SerializerUtils.writePropertyValue(writer, CommonModelNames.TYPE, item.getType());
                SerializerUtils.writePropertyValue(writer, CommonModelNames.CONSTRAINT_MESSAGE, item.getConstraintMessage());
                SerializerUtils.writePropertyValue(writer, CefNames.I18N_RESOURCE_INFO_PREFIX, item.getI18nResourceInfoPrefix());
                //cef上有关于字段的处理 ElementList
                writeElementList(writer, item, bizObject);
                SerializerUtils.writeEndObject(writer);
            }
        }
        //]
        SerializerUtils.WriteEndArray(writer);
    }

    private void writeElementList(JsonGenerator writer, GspUniqueConstraint item, GspCommonObject bizObject) {
        //ElementList
        SerializerUtils.writePropertyName(writer, CommonModelNames.ELEMENT_LIST);

        BaseList<String> collection = item.getElementList();
        //[
        SerializerUtils.WriteStartArray(writer);
        if (collection.size() > 0) {
            for (String elementId : collection) {
                IGspCommonElement element = bizObject.findElement(elementId);
                getFieldSerializer().serialize(element, writer, null);
            }
        }
        //]
        SerializerUtils.WriteEndArray(writer);
    }

    private void writeGspHirarcheInfo(JsonGenerator writer, GspCommonObject bizObject) {
//        SerializerUtils.writePropertyName(writer, CommonModelNames.HirarchyInfo);
//        SerializerUtils.writeStartObject(writer);
//        GSPHirarchyInfo hirarchyInfo = bizObject.HirarchyInfo;
//        if (hirarchyInfo != null)
//        {
//            WriteElementID(writer, CommonModelNames.ISDETAILELEMENT, hirarchyInfo.IsDetailElement);
//            WriteElementID(writer, CommonModelNames.LayerElement, hirarchyInfo.LayerElement);
//            WriteElementID(writer, CommonModelNames.ParentElement, hirarchyInfo.ParentElement);
//            WriteElementID(writer, CommonModelNames.ParentRefElement, hirarchyInfo.ParentRefElement);
//            WriteElementID(writer, CommonModelNames.PathElement, hirarchyInfo.PathElement);
//            SerializerUtils.WritePropertyValue(writer, CommonModelNames.PathGenerateType, hirarchyInfo.PathGenerateType);
//            SerializerUtils.WritePropertyValue(writer, CommonModelNames.PathLength, hirarchyInfo.PathLength);
//        }
//        SerializerUtils.writeEndObject(writer);
    }

    private void writeGspAssociationKeyCollection(JsonGenerator writer, GspCommonObject bizObject) {
        //外键集合
        SerializerUtils.writePropertyName(writer, CommonModelNames.KEYS);
        //[
        SerializerUtils.WriteStartArray(writer);
        if (bizObject.getKeys().size() > 0) {
            for (GspAssociationKey item : bizObject.getKeys()) {
                SerializerUtils.writePropertyValue_Object(writer, item);
            }
        }
        //]
        SerializerUtils.WriteEndArray(writer);
    }



    @Override
    protected final CefFieldSerializer getFieldSerializer() {
        return gspCommonDataTypeSerializer();
    }

    protected abstract CmElementSerializer gspCommonDataTypeSerializer();

    protected abstract void writeExtendObjectBaseProperty(JsonGenerator writer, IGspCommonObject bizObject);

    protected abstract void writeExtendObjectSelfProperty(JsonGenerator writer, IGspCommonObject bizObject);

}


